package com.blade.spring.framework.context;

import com.blade.spring.framework.beans.BLBeanFactory;
import com.blade.spring.framework.beans.BLBeanWrapper;
import com.blade.spring.framework.beans.config.BLBeanDefinition;
import com.blade.spring.framework.beans.support.BLBeanDefinitionReader;
import com.blade.spring.framework.beans.support.BLDefaultListableBeanFactory;

import java.util.List;
import java.util.Map;

/**
 * ClassName: BLApplicationContext
 * Description: TODO
 *
 * @author blade
 * @version 1.0
 * @Date 2020/12/16 10:01
 */
public class BLApplicationContext extends BLDefaultListableBeanFactory implements BLBeanFactory {

    /**
     * 配置文件的路径地址
     */
    private String[] configLocations;
    /**
     * 真正去定位配置文件的类
     */
    BLBeanDefinitionReader reader;

    public BLApplicationContext(String... configLocations) {
        this.configLocations = configLocations;
        refresh();
    }

    @Override
    protected void refresh() {
        //1.定位，定位配置文件
        reader = new BLBeanDefinitionReader(this.configLocations);
        //2.加载配置文件，扫描相关的类，把它们封装成beanDefinition
        List<BLBeanDefinition> beanDefinitions = reader.loadBeanDefinitions();
        //3.注册，把配置信息放到容器里面（伪IOC容器）
        doRegisterBeanDefinition(beanDefinitions);
        //4.把不是延时加载的类，要提前初始化
        doAutowired();
    }

    /**
     * 此处的注入，只处理非延时加载的情况
     */
    private void doAutowired() {
        for (Map.Entry<String, BLBeanDefinition> beanDefinitionEntry : super.beanDefinitionMap.entrySet()) {
            String beanName = beanDefinitionEntry.getKey();
            if (!beanDefinitionEntry.getValue().isLazyInit()){
                getBean(beanName);
            }


        }
    }

    private void doRegisterBeanDefinition(List<BLBeanDefinition> beanDefinitions) {

        for (BLBeanDefinition beanDefinition : beanDefinitions) {
            super.beanDefinitionMap.put(beanDefinition.getFactoryBeanName(),beanDefinition);
        }

    }

    @Override
    public Object getBean(String beanName) {

        /**
         * 初始化和注入分开是为了解决循环依赖的问题
         * class A{B b;}
         * class B{A a;}
         * 分不清是先有谁，后有谁。
         * 所以先不管依赖，先初始化，再注入。
         */
        //1.初始化
        BLBeanWrapper blBeanWrapper = instantiateBean(beanName, new BLBeanDefinition());
        //2.注入
        populateBean(beanName,new BLBeanDefinition(),blBeanWrapper);
        return null;
    }

    private void populateBean(String beanName, BLBeanDefinition blBeanDefinition, BLBeanWrapper blBeanWrapper) {

    }

    private BLBeanWrapper instantiateBean(String beanName, BLBeanDefinition blBeanDefinition) {
        //1.拿到要实例化的对象的类名

        //2.反射实例化，得到一个对象

        //3.把对象封装到BeanWrapper中

        //4.把BeanWrapper存到IOC容器中
        return null;
    }
}
